#!/usr/bin/perl

#
# We need to replace /Library/Internet Plug-Ins/JavaPluginCocoa.bundle if the one there is 
# older than the one in the 1.4 framework.
#
my $plugin_loc = "/Library/Internet Plug-Ins";
my $plugin_file = "$plugin_loc/JavaPluginCocoa.bundle";
my $framework_plugin_file = "/System/Library/Frameworks/JavaVM.framework/Versions/1.4/Resources/JavaPluginCocoa.bundle";

#
# If the plugin exists and is not a symlink, check its version and replace if it's older than the framework version
# If it is missing, then install the plugin from the framework
# If it's a symlink, just leave it alone
#
if ( -e $plugin_file ) {
	if ( ! ( -l $plugin_file) ) {    
		$plugin_version = bundle_version($plugin_file);
		$framework_plugin_version = bundle_version($framework_plugin_file);
	
		# If our framework version is greater than the "/Library/Internet Plug-Ins" version,
		# copy the framework version into the "/Library/Internet Plug-Ins" directory.
		if ( gt_version($framework_plugin_version, $plugin_version) ) {
			copy_framework_plugin();
		}
	}
}
else {
	copy_framework_plugin();
}

# Copy JavaPluginCocoa.bundle from the framework into /Library/Internet Plug-Ins
sub copy_framework_plugin {
	if ( -e $framework_plugin_file ) {
		# Copy from the framework
		my $returnval = system("/bin/cp -Rpf \"$framework_plugin_file\" \"$plugin_loc\"");
		if ( ! ($returnval==0) ) {
			print "Copy of \"$framework_plugin_file\" into \"$plugin_loc\" failed.\n";
			exit $returnval;
		}
		# Make sure 'admin' is the group
		my $returnval = system("/usr/bin/chgrp -R admin \"$plugin_file\"");
		if ( ! ($returnval==0) ) {
			print "Changing group ownership to 'admin' on \"$plugin_file\" failed.\n";
			exit $returnval;
		}
		# Make sure 'admin' and the owner have write permissions, other is read-only
		my $returnval = system("/bin/chmod -R g+w \"$plugin_file\"");
		if ( ! ($returnval==0) ) {
			print "Changing permissions on \"$plugin_file\" failed.\n";
			exit $returnval;
		}
	}
	else {
		print "The framework plugin, $framework_plugin_file, is missing! You may have a corrupt install of Java.\n";
		exit 1;
	}
}

exit 0;

#
# Parse the version.plist for a Bundle (e.g. JavaPluginCocoa.bundle) and return the CFBundleShortVersionString
# This script tries to be smart about getting the values for the <key>s in the version.plist. Since
# .plists are xml, there might be additional blank space, or it might be compressed (have newlines removed), so
# simply parsing line by line might not give the results you expect
#
sub bundle_version {
	my ($file) = @_;
	my $version = "";
	my $skip = 0;
	my $plist_dict_item;

	my $origSeparator = $/;
	$/ = \0; # Set the separator to \0 so we read the whole file in at once
	open (PLIST, "$file/Contents/version.plist") or $skip=1; # Try opening the app/bundle version file
	if ( ! $skip ) {
		my $plist = <PLIST>;
	
		# Extract the <dict> from the version.plist
		# note: does not handle nested dictionaries
		$plist =~ /<dict>(.*?)<\/dict>/gis;
		my $plist_dict = $1;
		if ( $plist_dict ) { # if there is a <dict> to parse
			my @plist_dict_items = split(/<key>/, $plist_dict); # make an array from all the <key>s	
			shift @plist_dict_items;
			foreach $plist_dict_item (@plist_dict_items) { # look at each of the <key>s
				$plist_dict_item =~ /(.*?)<\/key>.*?<string>(.*?)<\/string>/gis;
				if ( "$1" eq "CFBundleShortVersionString") {
					$version = $2;
					last;
				}
			}
		}	
		close(PLIST);
	}
	$/ = $origSeparator; # restore the separator	
	return $version;
}


#
# Compare two version strings as returned by bundle_version and if the first is greater than the second, return true
# e.g. 	gt_version("10.0.1","10.0.0") returns true
#
sub gt_version {
	my ($aa, $bb) = @_;

    my @splita = split(/\./, $aa);
    my @splitb = split(/\./, $bb);
	my $maxsubversions = 1;
	if ( scalar(@splita) >= scalar(@splitb) ) 	{ $maxsubversions = scalar(@splita); }
	else 										{ $maxsubversions = scalar(@splitb);	}

	
	my $a = 0; my $b = 0;
	my $counter = 0;
	while (($a == $b) and ($counter < $maxsubversions)) {
		if ( $counter < scalar(@splita) ) {
			$a = $splita[$counter];
		}
		else {
			$a = 0;
		}
		if ( $counter < scalar(@splitb) ) {
			$b = $splitb[$counter];
		}
		else {
			$b = 0;
		}
		$counter++;
	}
	return ( $a > $b );
}